package edu.hawaii.nearestneighbor.classifiers;

import java.util.List;

import edu.hawaii.nearestneighbor.classifications.Classification;
import edu.hawaii.nearestneighbor.util.DataPoint;
import edu.hawaii.nearestneighbor.util.NNutil;

/**
 * Provides methods for implementing the standard K-Nearest neighbor classifer.
 * 
 * @author Robert Puckett
 * 
 */
public class KNNClassifier implements Classifier {

  /**
   * Contains the number of neighbors to be used in the classification.
   */
  protected int k;

  /**
   * Creates an instance of KNNClassification and initializes the k value to 1.
   * 
   * @param k
   */
  public KNNClassifier() {
    this.k = 1;
  }

  /**
   * Creates an instance of KNNClassification and initializes the k value.
   * 
   * @param k the number of neighbors to use in classification.
   */
  public KNNClassifier(int k) {
    this.k = k;
  }

  /**
   * Classifies the point using k-NN algorithm.
   * @param data the set of data points used for classification.
   * @param test the point to be classified.
   * 
   * @return the classification of test.
   * @see edu.hawaii.nearestneighbor.classifiers.Classifier#Classify(java.util.List,
   *      edu.hawaii.nearestneighbor.util.DataPoint)
   */
  public Classification classify(List<DataPoint> data, DataPoint test) {
    // Find the k-nearest data points to the test point.
    List<DataPoint> kNearest = NNutil.findKNearest(data, test, k);

    // Finds the most often occurence of the state in the nearest points.
    return new Classification(NNutil.modeState(kNearest), k);

  }

  /**
   * Classifies the point using the k-NN algorithm.
   * @param data the total set of training data.
   * @param test the point to be classified.
   * @param k the number of neighbors to be utilized in classification.
   * @return the classification.
   */
  public static Classification classify(List<DataPoint> data, DataPoint test, int k) {
    // Find the k-nearest data points to the test point.
    List<DataPoint> kNearest = NNutil.findKNearest(data, test, k);

    // Finds the most often occurence of the state in the nearest points.
    return new Classification(NNutil.modeState(kNearest), k);

  }

  /*
   * (non-Javadoc)
   * 
   * @see edu.hawaii.nearestneighbor.classifiers.Classifier#Classify(java.util.List,
   *      edu.hawaii.nearestneighbor.util.DataPoint, int)
   */
  // public Classification Classify(List<DataPoint> data, DataPoint test, int distancetype) {
  // // Find the k-nearest data points to the test point.
  // List<DataPoint> kNearest = NNutil.findKNearest(data, test, k);
  //    
  // // Finds the most often occurence of the state in the nearest points.
  // return new Classification(NNutil.modeState(kNearest),k);
  // }
  /**
   * Sets the k value.
   * 
   * @param k the number of neighbors to use in classification.
   */
  public void setK(int k) {
    this.k = k;
  }

  /**
   * Gets the k value.
   * 
   * @return the number of neighbors to use in classification.
   */
  public int getK() {
    return k;
  }

  /*
   * Classifies the DataPoint according to nearest neighbor methods. @param p1 The DataPoint to be
   * classified. @param type The type of NN classification to run <ul> 0 = k-NN with Euclidean
   * Distance, using internal k value <li> 1 = k-NN with Statistical Confidence <li> 2 = k-NN with
   * Cam-Weighted Distances <li> 3 = k-NN <li> </ul> @return The state of nature.
   */
}
